/* Copyright (c) 2022 Hygon Corporation
 * Copyright (c) 2020-2022 Alibaba Cloud
 * 
 * This file is mainly copied from
 * https://github.com/inclavare-containers/rats-tls/tree/master/src/verifiers/csv/hygoncert.h.
 * and
 * https://github.com/inclavare-containers/rats-tls/tree/master/src/include/rats-tls/csv.h.
 * 
 * We changed some of the code to accommodate the csv-guest-module-tool.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef _HYGONCERT_H_
#define _HYGONCERT_H_

#include "csv-guest-module-tool.h"

typedef enum {
	KEY_USAGE_TYPE_HRK = 0,
	KEY_USAGE_TYPE_HSK = 0x13,
	KEY_USAGE_TYPE_INVALID = 0x1000,
	KEY_USAGE_TYPE_MIN = 0x1001,
	KEY_USAGE_TYPE_OCA = 0x1001,
	KEY_USAGE_TYPE_PEK = 0x1002,
	KEY_USAGE_TYPE_PDH = 0x1003,
	KEY_USAGE_TYPE_CEK = 0x1004,
	KEY_USAGE_TYPE_MAX = 0x1004,
} key_usage_t;

typedef enum {
	CURVE_ID_TYPE_INVALID = 0,
	CURVE_ID_TYPE_MIN     = 0X1,
	CURVE_ID_TYPE_P256    = 0x1,
	CURVE_ID_TYPE_P384    = 0x2,
	CURVE_ID_TYPE_SM2_256 = 0x3,
	CURVE_ID_TYPE_MAX     = 0X3,
} curve_id_t;

#define HYGON_SM2_UID_SIZE		256U
#define HYGON_ECC_UID_SIZE		HYGON_SM2_UID_SIZE
#define HYGON_CHIP_KEY_ID_SIZE		16U

/* structures for Hygon root certs */

#define HYGON_PUBKEY_SIZE		404U
#define HYGON_SIGNATURE_SIZE		144U
#define HYGON_ROOT_CERT_SIZE		832U

typedef struct hygon_pubkey {
	uint32_t curve_id;
	uint8_t qx[72];
	uint8_t qy[72];
	uint16_t userid_len;
	uint8_t userid[HYGON_SM2_UID_SIZE - sizeof(uint16_t)];
} __attribute__((__packed__)) hygon_pubkey_t;

typedef struct hygon_signature {
	uint8_t r[72];
	uint8_t s[72];
} __attribute__((__packed__)) hygon_signature_t;

typedef struct hygon_root_cert {
	uint32_t version;
	struct {
		uint8_t id[HYGON_CHIP_KEY_ID_SIZE];
	} key_id, certifying_id;
	uint32_t key_usage;
	uint8_t reserved1[24];
	union {
		uint8_t pubkey[4 + 72 * 2 + 256];
		hygon_pubkey_t ecc_pubkey;
	};
	uint8_t reserved2[108];
	union {
		uint8_t signature[72 * 2];
		hygon_signature_t ecc_sig;
	};
	uint8_t reserved3[112];
} __attribute__((__packed__)) hygon_root_cert_t;

/* structures for Hygon root certs */

#define HYGON_CSV_CERT_SIZE		2084U

typedef struct hygon_csv_cert {
	uint32_t version;
	uint8_t api_major;
	uint8_t api_minor;
	uint8_t reserved1;
	uint8_t reserved2;
	uint32_t pubkey_usage;
	uint32_t pubkey_algo;
	hygon_pubkey_t ecc_pubkey;
	uint8_t reserved3[624];
	uint32_t sig1_usage;
	uint32_t sig1_algo;
	hygon_signature_t ecc_sig1;
	uint8_t reserved4[368];
	uint32_t sig2_usage;
	uint32_t sig2_algo;
	hygon_signature_t ecc_sig2;
	uint8_t reserved5[368];
} __attribute__((__packed__)) hygon_csv_cert_t;

typedef struct hygon_csv_cert_chain {
	hygon_csv_cert_t pek_cert;
	hygon_csv_cert_t oca_cert;
	hygon_csv_cert_t cek_cert;
} __attribute__(()) hygon_csv_cert_chain_t;

CHECK_STRUCT_SIZE(hygon_pubkey_t, HYGON_PUBKEY_SIZE);
CHECK_STRUCT_SIZE(hygon_signature_t, HYGON_SIGNATURE_SIZE);
CHECK_STRUCT_SIZE(hygon_root_cert_t, HYGON_ROOT_CERT_SIZE);
CHECK_STRUCT_SIZE(hygon_csv_cert_t, HYGON_CSV_CERT_SIZE);

#define CSV_HSK_CEK_DEFAULT_DIR		"/opt/hygon/demo/csv/hsk_cek/"
#define HYGON_HSK_CEK_CERT_FILE		"hsk_cek.cert"
#define HYGON_KDS_SERVER_SITE		"https://cert.hygon.cn/hsk_cek?snumber="

int verify_hsk_cert(hygon_root_cert_t *cert);
int verify_cek_cert(hygon_root_cert_t *hsk_cert, hygon_csv_cert_t *cek_cert);
int verify_pek_cert(hygon_csv_cert_t *cek_cert, hygon_csv_cert_t *pek_cert);
int verify_hygon_certchain(hygon_csv_cert_t *pek_cert, const uint8_t *chip_id);
int verify_hygon_signature(const uint8_t *data, uint32_t data_len,
			   hygon_pubkey_t *pubkey, hygon_signature_t *sig);

#endif /* _HYGONCERT_H_ */
